#include "sheetheaderview.h"
#include "headerdelegate.h"

#include <QLineEdit>
#include <QDebug>
#include <QApplication>
#include <QMouseEvent>

static const int HandleWidth = 3;
static const int Space = 0;
class SheetHeaderViewPrivate
{
public:
    QMap<int, HeaderDelegate*> delegates;
    MatrixBase* matrix = nullptr;
};

SheetHeaderView::SheetHeaderView(Qt::Orientation ori, QWidget *parent) : QHeaderView(ori, parent)
{
    d_ptr = new SheetHeaderViewPrivate;
    setSectionsClickable(true);

    connect(this, SIGNAL(sectionResized(int, int, int)), this,
            SLOT(handleSectionResized(int)));
    connect(this, SIGNAL(sectionMoved(int, int, int)), this,
            SLOT(handleSectionMoved(int, int, int)));
}

SheetHeaderView::~SheetHeaderView()
{
    delete d_ptr;
}

void SheetHeaderView::setMatrix(MatrixBase *matrix)
{
    if (d_ptr->matrix != matrix) {
        d_ptr->matrix = matrix;
    }
}

void SheetHeaderView::relayoutDelegates()
{
    if (orientation() == Qt::Horizontal) {
        for (int i = 0; i < count(); ++i)
            d_ptr->delegates[i]->setGeometry(sectionViewportPosition(i), Space, sectionSize(i) - HandleWidth, height());
    } else {
        for (int i = 0; i < count(); ++i)
            d_ptr->delegates[i]->setGeometry(QRect(QPoint(Space, sectionViewportPosition(i)),
                                        QPoint(width() - HandleWidth, sectionViewportPosition(i) + sectionSize(i) - HandleWidth)));
    }
}

void SheetHeaderView::showEvent(QShowEvent *e)
{
    for (int i = 0; i < count(); i++) {
        if (!d_ptr->delegates[i]) {
            HeaderDelegate *delegate = new HeaderDelegate(orientation(), this);
            d_ptr->delegates[i] = delegate;
            d_ptr->delegates[i]->setIndex(i + 1);
            delegate->hide();
            delegate->setMatrix(d_ptr->matrix);
            connect(delegate, SIGNAL(clicked(QPoint)), this, SLOT(onDelegateClicked(QPoint)));

            if (this->orientation() == Qt::Horizontal)
                setMinimumHeight(delegate->sizeHint().height());
            else
                setMinimumWidth(delegate->sizeHint().width());
        }
    }

    if (orientation() == Qt::Horizontal) {
        for (int i = 0; i < count(); i++) {
            d_ptr->delegates[i]->setGeometry(sectionViewportPosition(i), Space, sectionSize(i) - HandleWidth, height());
            d_ptr->delegates[i]->show();
        }
    } else {
        for (int i = 0; i < count(); i++) {
            d_ptr->delegates[i]->setGeometry(QRect(QPoint(Space, sectionViewportPosition(i)),
                                        QPoint(width() - HandleWidth, sectionViewportPosition(i) + sectionSize(i) - HandleWidth)));
            d_ptr->delegates[i]->show();
        }
    }

    QHeaderView::showEvent(e);
}

void SheetHeaderView::handleSectionResized(int i)
{
    if (orientation() == Qt::Horizontal) {
        for (int j = visualIndex(i); j < count(); j++) {
            int logical = logicalIndex(j);
            d_ptr->delegates[logical]->setGeometry(sectionViewportPosition(logical), Space,
                                        sectionSize(logical) - HandleWidth, height());
            d_ptr->delegates[logical]->setIndex(logical + 1);
        }
    } else {
        for (int j = visualIndex(i); j < count(); j++) {
            int logical = logicalIndex(j);
            d_ptr->delegates[logical]->setGeometry(QRect(QPoint(Space, sectionViewportPosition(logical)),
                                              QPoint(width() - HandleWidth, sectionViewportPosition(logical) + sectionSize(logical) - HandleWidth)));
            d_ptr->delegates[logical]->setIndex(logical + 1);
        }
    }
}
void SheetHeaderView::handleSectionMoved(int logic, int oldVisualIndex, int newVisualIndex)
{
    Q_UNUSED(logic)
    if (orientation() == Qt::Horizontal) {
        for (int i = qMin(oldVisualIndex, newVisualIndex); i < count(); i++){
            int logical = logicalIndex(i);
            d_ptr->delegates[logical]->setGeometry(sectionViewportPosition(logical), Space,
                                        sectionSize(logical) - HandleWidth, height());
        }
    } else {
        for (int i = qMin(oldVisualIndex, newVisualIndex);i < count(); i++){
            int logical = logicalIndex(i);
            d_ptr->delegates[logical]->setGeometry(QRect(QPoint(Space, sectionViewportPosition(logical)),
                                              QPoint(width() - HandleWidth, sectionViewportPosition(logical) + sectionSize(logical) - HandleWidth)));
        }
    }
}

void SheetHeaderView::onDelegateClicked(const QPoint &pos)
{
//    QMouseEvent ms(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
//    qApp->sendEvent(this, &ms);

    HeaderDelegate* delegate = qobject_cast<HeaderDelegate*>(sender());
    selectionModel()->clear();

    if (delegate->orientation() == Qt::Horizontal) {
        // select column
        int rows = model()->rowCount();
        for (int i = 0; i < rows; ++i) {
            QModelIndex index = this->model()->index(i, delegate->index() - 1);
            selectionModel()->select(index, QItemSelectionModel::Select);
        }
    } else {
        // select row
        int cols = model()->columnCount();
        for (int i = 0; i < cols; ++i) {
            QModelIndex index = this->model()->index(delegate->index() - 1, i);
            selectionModel()->select(index, QItemSelectionModel::Select);
        }
    }

}
